package org.zergle.utils;

/**
 * 字符队列
 * 
 * @author Johnson.Lee
 */
public class CharQueue {
	private Entry header;
	private int size;

	/**
	 * 默认构造
	 */
	public CharQueue() {
	}

	/**
	 * 检索队列头，但不移除队伍头
	 * 
	 * @return 返回队列头
	 * @throws EmptyQueueException
	 *             当队列为空时，抛出此异常
	 */
	public char peek() throws EmptyQueueException {
		if (this.size == 0) {
			throw new EmptyQueueException();
		}
		return this.header.value;
	}

	/**
	 * 将字符插入此队列
	 * 
	 * @param c
	 *            字符的ASCII码
	 */
	public void offer(int c) {
		this.offer((char) c);
	}

	/**
	 * 将字符插入此队列
	 * 
	 * @param c
	 *            字符的ASCII码
	 */
	public void offer(char c) {
		this.size++;
		if (this.header == null) {
			this.header = new Entry(null, null, c);
			this.header.next = this.header.previous = this.header;
			;
		} else {
			Entry entry = new Entry(this.header.previous, this.header, c);
			this.header.previous.next = entry;
			this.header.previous = entry;
		}
	}

	/**
	 * 检索并移除队列头
	 * 
	 * @return 此队列的第一个元素
	 * @throws EmptyQueueException
	 *             当队列为空时抛出此异常
	 */
	public char poll() throws EmptyQueueException {
		char c = this.peek();
		Entry newHeader = this.header.next;
		newHeader.previous = this.header.previous;
		newHeader.previous.next = newHeader;
		this.header = newHeader;
		this.size--;
		return c;
	}

	/**
	 * 检索指定字符在队列中的索引
	 * 
	 * @param c
	 *            字符
	 * @return 指定字符在队列中第一次出现的位置
	 */
	public int indexOf(char c) {
		Entry entry = this.header;
		for (int i = 0; i < size; i++) {
			if (entry.value == c)
				return i;
			entry = entry.next;
		}
		return -1;
	}

	/**
	 * 检索指定字符在队列中的索引
	 * 
	 * @param c
	 *            字符ASCII码
	 * @return 指定字符在队列中第一次出现的位置
	 */
	public int indexOf(int c) {
		return this.indexOf((char) c);
	}

	/**
	 * 清空队列
	 */
	public void clear() {
		this.size = 0;
		this.header = null;
	}

	/**
	 * 测试此字符队列是否为空
	 * 
	 * @return 当且仅当此字符队列size() <= 0则返回true，否则返回false
	 */
	public boolean isEmpty() {
		return this.size <= 0;
	}

	/**
	 * 返回此队列的大小
	 * 
	 * @return 此队列中字符的数量
	 */
	public int size() {
		return this.size;
	}

	/**
	 * 返回此队列的字符串表示形式
	 * 
	 * @return 此队列的字符串表示形式
	 */
	public String toString() {
		char[] buf = new char[size];
		Entry entry = this.header;
		for (int i = 0; i < size; i++) {
			buf[i] = entry.value;
			entry = entry.next;
		}
		return new String(buf);
	}

	private class Entry {
		Entry previous;
		Entry next;
		char value;

		Entry(Entry previous, Entry next) {
			this(previous, next, (char) -1);
		}

		Entry(Entry previous, Entry next, char c) {
			this.previous = previous;
			this.next = next;
			this.value = c;
		}
	}
}
